package com.ruoyi.datastatistics.service.impl;

import com.github.pagehelper.PageHelper;
import com.ruoyi.basedata.domain.MeterSheets;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.datastatistics.mapper.HomepageMapper;
import com.ruoyi.datastatistics.service.HomepageService;
import com.ruoyi.datastatistics.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;

/**
 * 主页相关Service层实现类
 *
 * @author TsingYu
 * @version 2.0
 * @date 2024/6/24 16:19
 */
@Service
@Slf4j
public class HomepageServiceImpl implements HomepageService {

    private final HomepageMapper homepageMapper;
    private final SqlSessionFactory sqlSessionFactory;

    public HomepageServiceImpl(HomepageMapper homepageMapper, SqlSessionFactory sqlSessionFactory) {
        this.homepageMapper = homepageMapper;
        this.sqlSessionFactory = sqlSessionFactory;
    }

    /**
     * 小表主页数据-基础
     *
     * @param map map
     * @return Map
     */
    @Override
    public Map<String, Object> getHomepageDataForXb(Map<String, Object> map) {
        Map<String, Object> returnMap = new HashMap<>(15);
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 打开 SqlSession
            HomepageMapper mapper = session.getMapper(HomepageMapper.class);
            // 小表数量
            int count = mapper.countXbQty(map);
            returnMap.put("count", count);
            // 本月新增小表数
            map.put("month", true);
            int qtyAddedThisMonth = mapper.countXbQty(map);
            returnMap.put("thisMonthCount", qtyAddedThisMonth);
            // 本年新增小表数
            map.put("month", false);
            map.put("year", true);
            int thisYearCount = mapper.countXbQty(map);
            returnMap.put("thisYearCount", thisYearCount);
            // 昨日用水量
            List<Map<String, Object>> yesterdayUsage = mapper.statisticUsageXb(map);
            returnMap.put("yesterdayUsage", CollectionUtils.isEmpty(yesterdayUsage) ? 0 : MapUtils.getObject(yesterdayUsage.get(0), "usage"));
            // 上月用水量
            map.put("month", true);
            List<Map<String, Object>> lastMonthUsage = mapper.statisticUsageXb(map);
            returnMap.put("lastMonthUsage", CollectionUtils.isEmpty(lastMonthUsage) ? 0 : MapUtils.getObject(lastMonthUsage.get(0), "usage"));
            // 小表绑定的用户数量
            map.put("year", false);
            List<Map<String, Object>> userCount = mapper.countAccountsXb(map);
            returnMap.put("userCount", CollectionUtils.isEmpty(userCount) ? 0 : MapUtils.getObject(userCount.get(0), "count"));
            // 集中器数量
            List<Map<String, Object>> concentratorCount = mapper.countConcentratorXb(map);
            returnMap.put("concentratorCount", CollectionUtils.isEmpty(concentratorCount) ? 0 : MapUtils.getObject(concentratorCount.get(0), "count"));
            // 采集器数量
            List<Map<String, Object>> collectorCount = mapper.countCollectorXb(map);
            returnMap.put("collectorCount", CollectionUtils.isEmpty(collectorCount) ? 0 : MapUtils.getObject(collectorCount.get(0), "count"));
            // 根据预警类型，统计预警数量
            List<Map<String, Object>> warn = mapper.statisticWarnXb(map);
            returnMap.put("warn", warn);
            // 小表昨日抄回数
            map.put("beginDate", LocalDate.now().minusDays(1).toString());
            map.put("endDate", LocalDate.now().minusDays(1).toString());
            map.put("terminalType", 2);
            List<CopyVO> copyData = mapper.statisticCopy(map);
            if (CollectionUtils.isNotEmpty(copyData)) {
                returnMap.put("yesterdayCopyCount", copyData.get(0).getCopyCount());
            } else {
                returnMap.put("yesterdayCopyCount", 0);
            }
        } catch (Exception e) {
            log.error("查询出错", e);
        }
        return returnMap;
    }


    /**
     * 小表主页数据-抄回数据
     *
     * @param map map
     * @return Map
     */
    @Override
    public Map<String, Object> getHomepageCopyDataForXb(Map<String, Object> map) {
        Map<String, Object> returnMap = new HashMap<>(4);
        Integer days = MapUtils.getInteger(map, "days");
        if (days != null){
            map.put("beginDate", LocalDate.now().minusDays(days).toString());
            map.put("endDate", LocalDate.now().minusDays(1).toString());
        }
        map.put("terminalType", 2);
        // 小表抄回数据
        List<CopyVO> copyData = homepageMapper.statisticCopy(map);
        returnMap.put("copyData", copyData);
        return returnMap;
    }

    /**
     * 小表主页数据-月用量数据
     *
     * @param map map
     * @return Map
     */
    @Override
    public List<UsageVO> getHomepageMonthUsageDataForXb(Map<String, Object> map) {
        // 本年每月的月用量
        List<UsageVO> usage = homepageMapper.statisticUsageByMonthXb(map);
        String begin = MapUtils.getString(map,"beginDate");
        String end = MapUtils.getString(map,"endDate");
        List<String> yearMonthList = DateUtils.generateYearMonthStringListBetweenTwoYearMonth(begin, end);
        return getAllDateUsages(usage, yearMonthList);
    }

    /**
     * 将数据里缺少的日期数据补全
     *
     * @param usage    待补全数据
     * @param dateList 所有日期序列
     * @return 补全数据
     */
    private List<UsageVO> getAllDateUsages(List<UsageVO> usage, List<String> dateList) {
        if (CollectionUtils.isEmpty(dateList)) {
            return usage;
        }
        Map<String, UsageVO> usageMap = new LinkedHashMap<>(32);
        for (String date : dateList) {
            for (UsageVO vo : usage) {
                if (date.equals(vo.getDate())) {
                    usageMap.put(date, vo);
                }
            }
            UsageVO u = new UsageVO();
            u.setDate(date);
            u.setUsage(null);
            usageMap.putIfAbsent(date, u);
        }
        return new ArrayList<>(usageMap.values());
    }


    /**
     * 小表主页数据-日用量数据
     *
     * @param map map
     * @return Map
     */
    @Override
    public List<UsageVO> getHomepageDayUsageDataForXb(Map<String, Object> map) {
        // 本月每天的日用量
        List<UsageVO> usage = homepageMapper.statisticUsageByDayXb(map);
        String begin = MapUtils.getString(map, "beginDate");
        String end = MapUtils.getString(map, "endDate");
        List<String> dateList = DateUtils.generateDateStringListBetweenTwoDate(begin, end);
        return getAllDateUsages(usage, dateList);
    }

    /**
     * 根据小表类型统计小表数量
     *
     * @param map map
     * @return Map
     */
    @Override
    public List<XbTypeStatisticVO> getXbCountByType(Map<String, Object> map) {
        return homepageMapper.statisticTypeXb(map);
    }

    /**
     * 获取小表昨日用量前N设备
     *
     * @param map map
     * @return List
     */
    @Override
    public List<DbUsageVO> getYesterdayXbUsageTopN(Map<String, Object> map) {
        PageHelper.clearPage();
        return homepageMapper.statisticXbUsageTopN(map);
    }

    /**
     * 大表主页数据
     *
     * @param map map
     * @return Map
     */
    @Override
    public Map<String, Object> getHomepageDataForDb(Map<String, Object> map) {
        Map<String, Object> returnMap = new HashMap<>(15);
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 打开 SqlSession
            HomepageMapper mapper = session.getMapper(HomepageMapper.class);
            // 大表数量
            int count = mapper.countDbQty(map);
            returnMap.put("count", count);
            // 本月新增大表数
            map.put("month", true);
            int qtyAddedThisMonth = mapper.countDbQty(map);
            returnMap.put("thisMonthCount", qtyAddedThisMonth);
            // 本年新增大表数
            map.put("month", false);
            map.put("year", true);
            int thisYearCount = mapper.countDbQty(map);
            returnMap.put("thisYearCount", thisYearCount);
            // 大表绑定的用户数量
            map.put("year", false);
            int userCount = mapper.countAccountsDb(map);
            returnMap.put("userCount", userCount);
            // 昨日用水量
            BigDecimal yesterdayUsage = mapper.statisticUsageDb(map);
            returnMap.put("yesterdayUsage", yesterdayUsage);
            // 上月用水量
            map.put("month", true);
            BigDecimal lastMonthUsage = mapper.statisticUsageDb(map);
            returnMap.put("lastMonthUsage", lastMonthUsage);
            // 在线设备数量
            int onlineCount = mapper.countOnlineDb(map);
            returnMap.put("onlineCount", onlineCount);
            // 离线设备数量
            returnMap.put("offlineCount", count - onlineCount);
            // 根据预警类型，统计大表昨日预警数量
            List<Map<String, Object>> warn = mapper.statisticWarnDb(map);
            returnMap.put("warn", warn);
            // 大表昨日抄回数
            map.put("beginDate", LocalDate.now().minusDays(1).toString());
            map.put("endDate", LocalDate.now().minusDays(1).toString());
            map.put("terminalType", 1);
            List<CopyVO> copyVO = mapper.statisticCopy(map);
            if (CollectionUtils.isNotEmpty(copyVO)){
                returnMap.put("copyCount", copyVO.get(0).getCopyCount());
            }else {
                returnMap.put("copyCount", 0);
            }
            // 统计大表昨日预警总数量
            int warnTotalCount = 0;
            for (Map<String, Object> obj : warn) {
                Integer warnCount = MapUtils.getInteger(obj, "warnCount");
                if (warnCount != null) {
                    warnTotalCount = warnTotalCount + warnCount;
                }
            }
            returnMap.put("warnTotalCount", warnTotalCount);
        } catch (Exception e) {
            log.error("查询出错", e);
        }
        return returnMap;
    }

    /**
     * 获取大表昨日用量前十设备
     *
     * @param map map
     * @return List
     */
    @Override
    public List<DbUsageVO> getYesterdayDbUsageTop10(Map<String, Object> map) {
        PageHelper.clearPage();
        return homepageMapper.statisticDbUsageTop10(map);
    }

    /**
     * 获取大表昨日夜间小流前十设备
     *
     * @param map map
     * @return List
     */
    @Override
    public List<DbUsageVO> getYesterdayDbNightMinFlowTop10(Map<String, Object> map) {
        PageHelper.clearPage();
        return homepageMapper.statisticNightMinFlowTop10(map);
    }

    /**
     * 大表主页数据-月用量数据
     *
     * @param map map
     * @return Map
     */
    @Override
    public List<UsageVO> getHomepageMonthUsageDataForDb(Map<String, Object> map) {
        // 本年每月的月用量
        List<UsageVO> usage = homepageMapper.statisticUsageByMonthDb(map);
        String begin = MapUtils.getString(map,"beginDate");
        String end = MapUtils.getString(map,"endDate");
        List<String> yearMonthList = DateUtils.generateYearMonthStringListBetweenTwoYearMonth(begin, end);
        return getAllDateUsages(usage, yearMonthList);
    }

    /**
     * 大表主页数据-日用量数据
     *
     * @param map map
     * @return Map
     */
    @Override
    public List<UsageVO> getHomepageDayUsageDataForDb(Map<String, Object> map) {
        // 本月每天的日用量
        List<UsageVO> usage = homepageMapper.statisticUsageByDayDb(map);
        String begin = MapUtils.getString(map,"beginDate");
        String end = MapUtils.getString(map,"endDate");
        List<String> dateList = DateUtils.generateDateStringListBetweenTwoDate(begin, end);
        return getAllDateUsages(usage, dateList);
    }

    @Override
    public Map<String, Object> getTerminalDateGroupBySheetsId(Map<String, Object> map) {
        Map<String, Object> returnMap = new HashMap<>(4);
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 打开 SqlSession
            HomepageMapper mapper = session.getMapper(HomepageMapper.class);
            // 小表专用区域
            map.put("deviceType", 1);
            List<MeterSheets> sheetsList = mapper.selectSheets(map);
            map.put("groupBySheet", true);
            // 小表抄表率
            map.put("beginDate", LocalDate.now().minusDays(1).toString());
            map.put("endDate", LocalDate.now().minusDays(1).toString());
            map.put("terminalType", 2);
            List<CopyVO> copies = mapper.statisticCopy(map);
            // 小表数量分区域
            List<Map<String, Object>> xbQty = mapper.countXbQtyGroupBySheetsId(map);
            // 集中器分区域
            List<Map<String, Object>> concentratorCount = mapper.countConcentratorXb(map);
            // 采集器分区域
            List<Map<String, Object>> collectorCount = mapper.countCollectorXb(map);
            // 用户数分区域
            List<Map<String, Object>> userCount = mapper.countAccountsXb(map);
            // 最新读数和读取时间
            List<Map<String, Object>> readNumAndTime = mapper.statisticXbReadNumAndTime(map);
            // 组装小表数据
            List<Map<String, Object>> xbDataList = new ArrayList<>(sheetsList.size());
            for (MeterSheets sheets : sheetsList) {
                Map<String, Object> resultMap = new HashMap<>(20);
                resultMap.put("sheetsId", sheets.getId());
                resultMap.put("sheetsCode", sheets.getSheetsCode());
                resultMap.put("sheetsName", sheets.getSheetsName());
                resultMap.put("lng", StringUtils.nvl(sheets.getLng(), StringUtils.EMPTY));
                resultMap.put("lat", StringUtils.nvl(sheets.getLat(), StringUtils.EMPTY));
                resultMap.put("deviceType", sheets.getDeviceType());
                resultMap.put("copyRate", 0.00);
                resultMap.put("count", 0);
                resultMap.put("userCount", 0);
                resultMap.put("concentratorCount", 0);
                resultMap.put("collectorCount", 0);
                resultMap.put("latestReadNum", 0.00);
                resultMap.put("latestReadTime", StringUtils.EMPTY);
                // 小表昨日抄表率
                for (CopyVO copyVO : copies) {
                    if (Objects.equals(sheets.getId(), copyVO.getSheetsId())) {
                        resultMap.put("copyRate", copyVO.getCopyRate());
                        break;
                    }
                }
                // 小表数量
                for (Map<String, Object> xb : xbQty) {
                    Long sheetsId = MapUtils.getLong(xb, "sheetsId");
                    if (Objects.equals(sheets.getId(), sheetsId)) {
                        resultMap.put("count", xb.get("count"));
                        break;
                    }
                }
                // 小表用户数量
                for (Map<String, Object> uc : userCount) {
                    Long sheetsId = MapUtils.getLong(uc, "sheetsId");
                    if (Objects.equals(sheets.getId(), sheetsId)) {
                        resultMap.put("userCount", uc.get("count"));
                        break;
                    }
                }
                // 集中器数量
                for (Map<String, Object> concentrator : concentratorCount) {
                    Long sheetsId = MapUtils.getLong(concentrator, "sheetsId");
                    if (Objects.equals(sheets.getId(), sheetsId)) {
                        resultMap.put("concentratorCount", concentrator.get("count"));
                        break;
                    }
                }
                // 采集器数量
                for (Map<String, Object> collector : collectorCount) {
                    Long sheetsId = MapUtils.getLong(collector, "sheetsId");
                    if (Objects.equals(sheets.getId(), sheetsId)) {
                        resultMap.put("collectorCount", collector.get("count"));
                        break;
                    }
                }
                // 最新读数和读取时间
                for (Map<String, Object> o : readNumAndTime) {
                    Long sheetsId = MapUtils.getLong(o, "sheetsId");
                    if (Objects.equals(sheets.getId(), sheetsId)) {
                        resultMap.put("latestReadNum", o.get("readNum"));
                        resultMap.put("latestReadTime", o.get("readTime"));
                        break;
                    }
                }
                xbDataList.add(resultMap);
            }
            returnMap.put("xb", xbDataList);
            // 大表设备
            List<Map<String, Object>> dbs = mapper.selectTerminals(map);
            returnMap.put("db", dbs);
        } catch (Exception e) {
            log.error("查询出错", e);
        }
        return returnMap;
    }

    @Override
    public Map<String, Object> getDataForBigScreen(Map<String, Object> map) {
        Map<String, Object> resultMap = new HashMap<>(6);
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 打开 SqlSession
            HomepageMapper mapper = session.getMapper(HomepageMapper.class);
            // 小表数量
            int xbCount = mapper.countXbQty(map);
            resultMap.put("xbCount", xbCount);
            // 大表数量
            int dbCount = mapper.countDbQty(map);
            resultMap.put("dbCount", dbCount);
            // 小表用户数量
            List<Map<String, Object>> xbUserCount = mapper.countAccountsXb(map);
            resultMap.put("xbUserCount", CollectionUtils.isEmpty(xbUserCount) ? 0 : MapUtils.getObject(xbUserCount.get(0), "count"));
            // 大表用户数量
            int dbUserCount = mapper.countAccountsDb(map);
            resultMap.put("dbUserCount", dbUserCount);
            // 小表昨日抄回数
            map.put("beginDate", LocalDate.now().minusDays(1).toString());
            map.put("endDate", LocalDate.now().minusDays(1).toString());
            map.put("terminalType", 2);
            List<CopyVO> copyData = mapper.statisticCopy(map);
            if (CollectionUtils.isNotEmpty(copyData)) {
                resultMap.put("xbYesterdayCopyCount", copyData.get(0).getCopyCount());
            } else {
                resultMap.put("xbYesterdayCopyCount", 0);
            }
            // 小表7天用量
            map.put("days", 7);
            List<UsageVO> xbUsage = mapper.statisticUsageByPreviousDaysXb(map);
            List<String> dateStringList = DateUtils.generateDateList(7);
            resultMap.put("xbUsage", getAllDateUsages(xbUsage, dateStringList));
            // 小表7天抄回数据
            map.put("beginDate", LocalDate.now().minusDays(7).toString());
            map.put("terminalType", 2);
            List<CopyVO> xbCopy = mapper.statisticCopy(map);
            resultMap.put("xbCopy", xbCopy);
            // 大表昨日抄回数
            map.put("beginDate", LocalDate.now().minusDays(1).toString());
            map.put("terminalType", 1);
            List<CopyVO> dbCopyVO = mapper.statisticCopy(map);
            if (CollectionUtils.isNotEmpty(dbCopyVO)) {
                resultMap.put("dbYesterdayCopyCount", dbCopyVO.get(0).getCopyCount());
            } else {
                resultMap.put("dbYesterdayCopyCount", 0);
            }
            // 根据预警类型，统计小表昨日预警数量
            List<Map<String, Object>> xbWarn = mapper.statisticWarnXb(map);
            resultMap.put("xbWarn", xbWarn);
            // 根据预警类型，统计大表昨日预警数量
            List<Map<String, Object>> dbWarn = mapper.statisticWarnDb(map);
            resultMap.put("dbWarn", dbWarn);
            // 大表7天用量
            map.put("days", 7);
            List<UsageVO> dbUsage = mapper.statisticUsageByPreviousDaysDb(map);
            resultMap.put("dbUsage", getAllDateUsages(dbUsage, dateStringList));
            // 大表7天抄回率
            map.put("beginDate", LocalDate.now().minusDays(7).toString());
            map.put("terminalType", 1);
            List<CopyVO> dbCopy = mapper.statisticCopy(map);
            resultMap.put("dbCopy", dbCopy);
            return resultMap;
        } catch (Exception e) {
            log.error("查询出错", e);
        }
        return resultMap;
    }

    /**
     * 获取昨日户表区域日用水量排名前五的区域
     *
     * @param map map
     * @return List
     */
    @Override
    public List<YesterdayAreaDosageVO> getYesterdayAreaTop5ForDosageXb(Map<String, Object> map) {
        PageHelper.clearPage();
        return homepageMapper.yesterdayAreaTop5ForDosageXb(map);
    }

}
